home *** CD-ROM | disk | FTP | other *** search
- /*
- * Simple mail user interface for KA9Q IP/TCP package.
- * A.D. Barksdale Garbee II, aka Bdale, N3EUA
- * Copyright 1986 Bdale Garbee, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- * Copyright 1987 1988 Dave Trulli NN2Z, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- *
- * Ported to NOS at 900120 by Anders Klemets SM0RGV.
- *
- * Userlogging, 'RM' and 'KM' implementation,
- * more-prompts for all types
- * 920307 and later, by Johan. K. Reinalda, WG7J/PA3DIS
- * 920719 and later, by Brian A. Lantz, KO4KS
- */
- #include "global.h"
- #include "ctype.h"
- #include "commands.h"
- #include "files.h"
- #ifdef MSDOS
- #include <io.h>
- #else
- #include <time.h>
- #endif
- #include "ftpserv.h"
- #include "smtp.h"
- #include "proc.h"
- #include "usock.h"
- #include "telnet.h"
- #include "mailbox.h"
- #include "bm.h"
- #include "color.h"
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: bmutil.c,v 1.40 1997/08/19 01:19:22 root Exp root $";
- #endif
-
- #ifndef UNIX
- #define SETVBUF
- #else
- #include <sys/stat.h>
- #endif
-
-
- #ifdef SETVBUF
- #define MYBUF 1024
- #endif
-
- static void readareas (const char *name);
- void freeareas (void);
- static int is_area2 (const char *name);
-
- extern int mbx_data (struct mbx * m, struct list * cclist, char *extra, int returnreceipt);
- extern int dombroute (int argc, char *argv[], void *p);
- extern void updateCtl (const char *who, struct let * info);
- extern int makeBBSbid (char *bid, int bidlen, char *line);
-
- #ifdef SAMCALLB
- extern char *cb_lookname (char *);
- #endif
-
- #ifdef MAILCMDS
- char Badmsg[] = "Invalid Message number %d\n";
- static char Badrange[] = "Invalid Message range '%d - %d'\n";
- char Nomail[] = "No messages\n";
- static char NoMsgs[] = "No message numbers given\n";
- static char anymore[] = "More(N=no)? ";
- static int readnotes (struct mbx * m, int already);
- static long isnewmail (struct mbx * m);
- static int initnotes (struct mbx * m);
- static void noteheader (struct mbx * m, int usebid);
- static void close_notes (int a, void *b, void *c);
- static void mfclose (struct mbx * m);
- #endif
-
- int lockit (struct mbx * m);
- extern char *nntp_name_expansion (char *name);
- static void dodeleting (struct mbx * m, int msg);
- static int is_area (const char *name, const char *listfile);
- char *mblookname (struct mbx * m, char *str);
- void notifynewmail (struct mbx * m);
- void backEmUp (int len);
- #ifdef SAMCALLB
- void leadingCaps (char *str, int others);
- #endif
-
- static char logdelmsg[] = "Msg %d in area '%s' made %s by '%s'";
-
- const char hitEnter[] = "Hit enter to continue";
-
- extern int MBnoReturnReceipt;
-
-
- FILE *subdir_fopen (char *name, const char *mode);
-
- FILE *
- subdir_fopen (char *name, const char *mode)
- {
- FILE *fp;
- char *cp;
-
- #undef ENOENT
- #define ENOENT 2
-
- if ((fp = fopen (name, mode)) != (FILE *) 0)
- return fp;
- if ((errno == ENOENT) && !strchr (mode, 'r')) {
- cp = &name[1];
- while ((cp = strpbrk (cp, "/\\")) != (char *) 0) {
- *cp = 0;
- if (access (name, 0))
- if (mkdir (name, 0777))
- return ((FILE *) 0);
- *cp++ = '/';
- }
- fp = fopen (name, mode);
- return fp; /* NULL if STILL not opened */
- }
- return ((FILE *) 0);
- }
-
-
-
- #ifdef MAILBOX
- #ifdef MAILCMDS
-
- static int
- initnotes (struct mbx *m)
- {
- char buf[256];
- int wasit = 0;
- #ifdef USERLOG
- register struct let *cmsg;
- int i;
- #endif
-
- if (m->mfile != NULLFILE) {
- (void) fclose (m->mfile);
- wasit = m->nmsgs;
- }
- sprintf (buf, "%s/%s.txt", Mailspool, m->area);
- if ((m->mfile = subdir_fopen (buf, READ_TEXT)) == NULLFILE)
- return 0;
- m->mboxsize = (long) filelength (fileno (m->mfile));
- if (!(m->sid & MBX_SID) && !stricmp (m->area, m->name)) /* our private mail area */
- m->mysize = m->mboxsize;
- m->nmsgs = 0;
- m->change &= CHG_SPECIAL;
- m->newmsgs = 0;
- m->newmsgsonentry = 0;
- m->anyread = 0;
- /* Allocate space for reading messages */
- (void) readnotes (m, wasit);
- #ifdef USERLOG
- m->current = 0; /*reset it*/
- if (m->nmsgs)
- for (cmsg = &m->mbox[1], i = 1; i <= m->nmsgs; i++, cmsg++)
- if ((cmsg->status & BM_READ) == 0) {
- m->current = i; /* first new message */
- break;
- }
- /* start at one if no new messages */
- if ((m->current == 0) && m->nmsgs)
- m->current++;
- #endif
- return 0;
- }
-
-
-
- /* readnotes assumes that ifile is pointing to the first
- * message that needs to be read. For initial reads of a
- * notesfile, this will be the beginning of the file. For
- * rereads when new mail arrives, it will be the first new
- * message.
- */
- static int
- readnotes (register struct mbx *m, int already)
- {
- register FILE *fp;
- char mailbox[128];
- long size;
- register int i, isit;
- register struct let *cmsg;
- struct let *new;
-
- m->newmsgs = m->hmsgs = 0;
- sprintf (mailbox, "%s/control/%s.ctl", Mailspool, m->area);
- if ((fp = subdir_fopen (mailbox, READ_BINARY)) != NULLFILE) {
- #if !defined(TNOS_68K)
- m->stdoutbuf = mallocw (MYBUF);
- (void) setvbuf (fp, m->stdoutbuf, _IOFBF, MYBUF);
- #endif
- size = (long) filelength (fileno (fp));
- new = (struct let *) mallocw ((unsigned long) size + sizeof (struct let));
-
- (void) fread (&new[1], (unsigned) size, 1, fp);
- (void) fclose (fp);
- if (already && !strcmp (m->area, m->name))
- memcpy (new, m->mbox, (unsigned) (already + 1) * sizeof (struct let));
-
- #if !defined(TNOS_68K)
- free (m->stdoutbuf);
- m->stdoutbuf = 0;
- #endif
- free (m->mbox);
- m->mbox = new;
- m->nmsgs = (int) (size / (long) sizeof (struct let));
-
- isit = issysarea (m->area);
- for (cmsg = &m->mbox[1], i = 1; i <= m->nmsgs; i++, cmsg++)
- if (isit) {
- if ((cmsg->bid > m->lastread) && !(cmsg->status & BM_DELETE))
- m->newmsgs++;
- else
- cmsg->status |= BM_READ;
- if (cmsg->status & BM_ONHOLD)
- m->hmsgs++;
- } else {
- if (!(cmsg->status & BM_READ))
- m->newmsgs++;
- if (cmsg->status & BM_ONHOLD)
- m->hmsgs++;
- }
- } else
- m->nmsgs = 0;
-
- m->newmsgsonentry = m->newmsgs;
- return 0;
- }
-
-
-
- /* Display the header to a listing */
- static void
- noteheader (struct mbx *m, int usebid)
- {
- char *area, *cp;
-
- area = strdup (m->area);
- while ((cp = strchr (area, '/')) != NULLCHAR)
- *cp = '.';
- bbscolorcls (m);
- tputs ("\nMail area: ");
- bbscolorchange (m, "09");
- tputs (area);
- bbscolorchange (m, "0B");
- tprintf (" %d ", m->nmsgs);
- bbscolorchange (m, "0F");
- tprintf ("message%s - ", m->nmsgs == 1 ? " " : "s ");
- bbscolorchange (m, "0B");
- tprintf ("%d ", m->newmsgs);
- bbscolorchange (m, "0F");
- tprintf ("new\n\nStat # TO FROM %s SUBJECT\n", (usebid) ? "MESSAGE ID " : " DATE SIZE");
- free (area);
- }
-
-
-
- /* list headers of a notesfile a message */
- /* Rearranged display - WG7J */
- int
- dolistnotes (int argc, char *argv[], void *p)
- {
- struct mbx *m;
- struct let *cmsg;
- char *cp, *s;
- char smtp_date[SLINELEN], smtp_from[SLINELEN];
- char smtp_subject[SLINELEN], tstring[LINELEN], type;
- char smtp_to[SLINELEN], smtp_bid[30];
- int start, stop;
- long size;
- int c, usemore = 0, lin;
- int usebid = 0;
- int headerseen = 0;
- #if 0
- char *area;
- #endif
- #ifdef USERLOG
- long msgid;
- #endif
-
- m = (struct mbx *) p;
-
- /*If this user doesn't have read-permissions,
- *we're not going to let him list anything - WG7J */
- if (m->privs & NO_READCMD) {
- tputs (Noperm);
- return 0;
- }
- if (m->mfile == NULLFILE) {
- if (!(m->privs & ALL_AREAS))
- tputs (Nomail);
- return 0;
- }
- if (m->stype == 'B') {
- usebid = 1;
- m->stype = ' ';
- }
- if (m->stype == '$')
- usebid = 1;
-
- if ((m->stype == 'S' || m->stype == '$' || m->stype == '>' || m->stype == '<') && argc == 1) {
- tputs ("Search criterium needed!\n");
- return 0;
- }
- if ((lin = m->morerows) != 0)
- usemore = 1; /* Display More prompt */
-
- #if 0
- noteheader (m, usebid);
- #endif
-
- stop = m->nmsgs;
- if (m->stype == 'L') { /* LL (List Latest) command */
- if (argc > 1)
- start = stop - atoi (argv[1]) + 1;
- else
- start = stop;
- if (start < 1)
- start = 1;
- } else {
- if ((m->stype == 'A') || (m->stype == '>') ||
- (m->stype == '<') || (m->stype == 'S') ||
- (m->stype == '$') || (m->stype == 'H') ||
- (m->stype == 'M')) {
- start = 1;
- stop = m->nmsgs;
- } else {
- if (argc > 1)
- start = atoi (argv[1]);
- else
- #ifdef USERLOG
- #if 0
- start = m->nmsgs - m->newmsgsonentry + 1;
- #else
- start = (m->newmsgsonentry) ? m->current : (m->nmsgs - m->newmsgsonentry + 1);
- #endif
- #else
- start = 1;
- #endif
- if (argc > 2)
- stop = atoi (argv[2]);
- }
- }
- if (stop > m->nmsgs)
- stop = m->nmsgs;
- if (start < 1 || start > stop) {
- if (!(m->privs & ALL_AREAS)) {
- if ((m->stype == ' ') || (m->stype == 'M'))
- tputs ("No new mail.\n");
- else
- tputs ("Invalid range.\n");
- }
- return 0;
- }
- if (m->sid & MBX_HTTP)
- tprintf ("<PRE>\n");
- for (cmsg = &m->mbox[start]; start <= stop; start++, cmsg++) {
- *smtp_date = '\0';
- *smtp_from = '\0';
- *smtp_subject = '\0';
- *smtp_to = '\0';
- *smtp_bid = '\0';
- type = ' ';
- fseek (m->mfile, cmsg->start, 0);
- size = cmsg->size;
- /* Be a little less selfish - WG7J */
- kwait (NULL);
-
- #ifdef USERLOG
- /* We need to get the id from the last message listed !
- * m->mbox[i].start (ie cmsg->start) points to the 'From ' line
- * next are the 'Received....' and 'ID...' lines
- * These are thes line added by our smtp server.
- * following the 'AA' is the number that we want ! - WG7J
- */
- #if 0
- if (start == stop) {
- #endif
- /*The 'From ' line*/
- (void) fgets (tstring, sizeof (tstring), m->mfile);
- size -= (long) strlen (tstring);
- /*The 'Received' line*/
- (void) fgets (tstring, sizeof (tstring), m->mfile);
- size -= (long) strlen (tstring);
- /*The 'ID' line*/
- (void) fgets (tstring, sizeof (tstring), m->mfile);
- size -= (long) strlen (tstring);
- /* find id number */
- #ifdef nope
- if ((cmsg->bid > m->lastread) && (cmsg->bid > m->newlastread))
- m->newlastread = cmsg->bid;
- #else
- if ((cp = strstr (tstring, "AA")) != NULLCHAR) {
- /*what follows is the message-number*/
- msgid = atol (cp + 2);
- if ((msgid > m->lastread) && (msgid > m->newlastread))
- m->newlastread = msgid;
- }
- #endif
- #if 0
- }
- #endif
- #endif
-
- while (size > 0 && fgets (tstring, sizeof (tstring), m->mfile) != NULLCHAR) {
- kwait (NULL);
- if (*tstring == '\n') /* end of header */
- break;
- size -= (long) strlen (tstring);
- rip (tstring);
- /* handle continuation later */
- if (*tstring == ' ' || *tstring == '\t')
- continue;
- switch (htype (tstring)) {
- case FROM:
- cp = getaddress (tstring, 0);
- strncpy (smtp_from, cp != NULLCHAR ? cp : "", 8);
- if ((cp = strchr (smtp_from, '@')) != NULLCHAR)
- *cp = '\0'; /* get rid of @-host or @-bbs field */
- break;
- case SUBJECT:
- trimright (tstring);
- cp = skipwhite (&tstring[9]);
- strncpy (smtp_subject, cp, 35);
- break;
- case MSGID:
- strncpy (smtp_bid, &tstring[12], 29);
- break;
- case DATE:
- if ((cp = strchr (tstring, ',')) == NULLCHAR)
- cp = &tstring[6];
- else
- cp++;
- /* skip spaces */
- while (*cp == ' ')
- cp++;
- if (strlen (cp) < 17)
- break; /* not a valid length */
- s = smtp_date;
- /* copy day */
- if (atoi (cp) < 10 && *cp != '0')
- *s++ = ' ';
- else
- *s++ = *cp++;
- *s++ = *cp++;
-
- *s++ = ' ';
- *s = '\0';
- while (*cp == ' ')
- cp++;
- strncat (s, cp, 3); /* copy month */
- #ifdef use_time
- cp += 3;
- while (*cp == ' ')
- cp++;
- /* skip year */
- while (isdigit (*cp))
- cp++;
- /* copy time */
- strncat (s, cp, 6); /* space hour : min */
- #endif
- break;
- case BBSTYPE:
- type = tstring[16];
- break;
- case TO:
- strncpy (smtp_to, &tstring[4], 13);
- break;
- case NOHEADER:
- default:
- break;
- }
- }
- if ((m->stype == 'M') && (cmsg->status & BM_READ))
- continue;
- if (m->stype == ' ' || m->stype == 'L' || m->stype == 'M' ||
- m->stype == 'A' || (type == m->stype && m->stype != ' ') ||
- ((m->stype == 'H') && (cmsg->status & BM_ONHOLD)) ||
- ((m->stype == 'S') && (strstr (strlwr (smtp_subject), argv[1]) != NULLCHAR)) ||
- ((m->stype == '<') && (strstr (strlwr (smtp_from), argv[1]) != NULLCHAR)) ||
- ((m->stype == '$') && (strstr (strlwr (smtp_bid), argv[1]) != NULLCHAR)) ||
- ((m->stype == '>') && (strstr (strlwr (smtp_to), argv[1]) != NULLCHAR))) {
- lin--;
- if ((cmsg->status & BM_DELETE) && !(m->privs & SYSOP_CMD))
- strcpy (smtp_subject, "[DELETED]");
- if (!(headerseen++ % 50))
- noteheader (m, usebid);
- bbscolorchange (m, "07");
- if (m->sid & MBX_HTTP)
- tprintf ("<A HREF=\"/bbs/message/%s/%d.html\">", m->area, start);
- tprintf ("%c%c%c%c%3d ", (start == m->current ? '>' : ' '),
- (cmsg->status & BM_DELETE ? 'D' :
- cmsg->status & BM_ONHOLD ? 'H' : ' '),
- (cmsg->status & BM_READ ? 'Y' : 'N'),
- (cmsg->status & BM_PERMANENT) ? 'P' : ' ',
- start);
- bbscolorchange (m, "0E");
- tprintf ("%13.13s ", smtp_to);
- bbscolorchange (m, "0C");
- tprintf ("%8.8s ", smtp_from);
- bbscolorchange (m, "07");
- if (usebid) {
- char *tmpbid, *bidptr = smtp_bid;
-
- if (*bidptr == '<')
- bidptr++;
- if ((tmpbid = strchr (bidptr, '@')) != NULLCHAR) {
- if (strstr (tmpbid, ".bbs") || strcmp (tmpbid, "@hamradio"))
- *tmpbid++ = 0;
- else {
- *tmpbid = '_';
- tmpbid = strchr (tmpbid, '.');
- if (tmpbid)
- *tmpbid = 0;
- }
- }
- (void) strupr (bidptr);
- tprintf ("%-13.13s ", bidptr);
- } else {
- tprintf ("%-7.7s ", smtp_date);
- tprintf ("%5ld ", cmsg->size);
- }
- bbscolorchange (m, "0E");
- tprintf ("%.34s\n", smtp_subject);
- if (m->sid & MBX_HTTP)
- tprintf ("</A>");
- #ifdef STATS_AREA
- STATS_addarea (0, 1, m->area);
- #endif
- }
- /* More prompting added - WG7J */
- if (usemore && lin == 0) {
- if (m->type == TELNET || m->type == TIP)
- c = tkeywait ("--More--", 0, m->linemode);
- else /* For AX.25 and NET/ROM connects - WG7J */
- c = mykeywait (anymore, m);
- #ifdef MBXTDISC
- start_timer (&m->tdisc);
- #endif
- if (c == -1 || c == 'q' || c == 'Q' || c == 'n' || c == 'N')
- break;
- #ifdef TNOS_68K
- if (c == '\l' || c == '\r')
- #else
- if (c == '\n' || c == '\r')
- #endif
- lin = 1;
- else
- lin = m->morerows;
-
- }
- }
- if (m->sid & MBX_HTTP)
- tprintf ("</PRE>\n");
- return 0;
- }
-
-
-
- /* save msg on stream - if noheader set don't output the header */
- int
- msgtofile (
- struct mbx *m,
- int msg,
- FILE * tfile, /* already open for write */
- int noheader,
- int numbered
- ) {
- char tstring[LINELEN];
- long size;
- int lineno = 0;
-
- if (m->mfile == NULLFILE) {
- tputs (Nomail);
- return -1;
- }
- fseek (m->mfile, m->mbox[msg].start, 0);
- size = m->mbox[msg].size;
-
- if (noheader) {
- /* skip header */
- while (size > 0 && fgets (tstring, sizeof (tstring) - 1, m->mfile) != NULLCHAR) {
- size -= (long) strlen (tstring);
- kwait (NULL);
- if (*tstring == '\n')
- break;
- }
- }
- while (size > 0 && fgets (tstring, sizeof (tstring) - 1, m->mfile)
- != NULLCHAR) {
- kwait (NULL);
- size -= (long) strlen (tstring);
- if (numbered)
- fprintf (tfile, "%02d) ", ++lineno);
- fputs (tstring, tfile);
- if (ferror (tfile)) {
- tputs ("Error writing mail file\n");
- return -1;
- }
- }
-
- return 0;
- }
-
-
-
- static void
- dodeleting (struct mbx *m, int msg)
- {
- switch (m->stype) {
- case 'U':
- m->mbox[msg].status &= ~BM_DELETE;
- tprintf ("Msg %d Un-Killed.\n", msg);
- break;
- case 'A':
- m->mbox[msg].status &= ~BM_ONHOLD;
- tprintf ("Msg %d Available.\n", msg);
- log (m->user, logdelmsg, msg, m->area, "available", m->name);
- break;
- case 'H':
- m->mbox[msg].status |= BM_ONHOLD;
- tprintf ("Msg %d Held.\n", msg);
- log (m->user, logdelmsg, msg, m->area, "held", m->name);
- break;
- case 'T':
- m->mbox[msg].status &= ~BM_PERMANENT;
- tprintf ("Msg %d Temporary.\n", msg);
- log (m->user, logdelmsg, msg, m->area, "temporary", m->name);
- break;
- case 'P':
- m->mbox[msg].status |= BM_PERMANENT;
- tprintf ("Msg %d Permanent.\n", msg);
- log (m->user, logdelmsg, msg, m->area, "permanent", m->name);
- break;
- default:
- if (m->mbox[msg].status & BM_PERMANENT)
- tprintf ("Can't kill message %d - Message is permanent!\n", msg);
- else {
- m->mbox[msg].status |= BM_DELETE;
- m->mbox[msg].status &= ~BM_ONHOLD;
- tprintf ("Msg %d Killed.\n", msg);
- if (!issysarea (m->area))
- m->change |= CHG_DELETE;
- }
- break;
- }
- statusCtl (m->area, "ctl", &m->mbox[msg], msg, 0);
- }
-
-
-
- /* dodelmsg - delete message in current notesfile */
- /* Modified to allow the 'KM' command. 920307 - WG7J */
- /* also handles holsing/releasing messages - KO4KS */
- int
- dodelmsg (int argc, char *argv[], void *p)
- {
- struct mbx *m;
- int msg = 0, i = 0;
- char *myargv[NARG];
- int myargc = 0;
- int maxmsg;
- struct let *cmsg;
- char *tmpbuf;
- int start, end;
-
- m = (struct mbx *) p;
-
- /* If this user doesn't have read-permissions,
- * we're not going to let him kill/hold anything;
- * allow anyone to kill/hold messages in areas
- * who's names start with 'nts' - WG7J
- */
- /* Check if we have permission to delete others mail */
- if ((m->privs & NO_READCMD) || (m->privs & NO_SENDCMD) ||
- (!(m->privs & FTP_WRITE) &&
- stricmp (m->area, m->name) &&
- strnicmp (m->area, "nts", 3))) {
- tputs (Noperm);
- return 0;
- }
- if ((m->stype == 'A' || m->stype == 'H' || m->stype == 'P' || m->stype == 'T') && !(m->privs & SYSOP_CMD)) {
- tputs (Noperm);
- return 0;
- }
- if (m->stype == 'S') {
- if (argc > 2) {
- myargc = msg = atoi (argv[1]);
- i = atoi (argv[2]);
- }
- if ((argc < 3) || !msg || !i)
- tputs (NoMsgs);
- else {
- for (; myargc <= i; myargc++) {
- m->mbox[myargc].status |= BM_DELETE;
- m->mbox[myargc].status &= ~BM_ONHOLD;
- statusCtl (m->area, "ctl", &m->mbox[myargc], myargc, 0);
- }
- if (!issysarea (m->area))
- m->change |= CHG_DELETE;
- tprintf ("Msgs %d to %d Killed.\n", msg, i);
- }
- return 0;
- }
- if (m->mfile == NULLFILE) {
- tputs (Nomail);
- return 0;
- }
- /*If this is the KM command, setup myargv[]
- *to contain up to NARG message numbers - WG7J
- */
- if (m->stype == 'M') {
- myargc = 1;
- /* scan all messsages to find read ones */
- maxmsg = min (m->nmsgs, NARG - 1);
- for (i = 1; i <= maxmsg; i++) {
- cmsg = &m->mbox[i];
- if (cmsg->status & BM_READ) { /*found a read msg!*/
- tmpbuf = mallocw (18); /*allocate space for the new argument*/
- myargv[myargc++] = itoa (i, tmpbuf, 10);
- }
- }
- if (myargc == 1) {
- tputs (NoMsgs);
- return 0;
- }
- argc = myargc;
- } else {
- if (argc == 1) {
- if (m->stype != 'A') {
- msg = m->current;
- dodeleting (m, msg);
- return 0;
- } else {
- for (i = 1; i <= m->nmsgs; i++) {
- cmsg = &m->mbox[i];
- if (cmsg->status & BM_ONHOLD) {
- cmsg->status &= ~BM_ONHOLD;
- statusCtl (m->area, "ctl", cmsg, i, 0);
- }
- }
- tputs ("All Messages Available.\n");
- return 0;
- }
- }
- /*simply point to the old arguments*/
- for (i = 1; i < argc; i++)
- myargv[i] = argv[i];
- }
-
- /* See if x - y format was used and use a for i = x to y loop */
- if (argc > 2 && myargv[2][0] == '-') { /*lint !e644 */
- start = atoi (myargv[1]);
- if (myargv[2][1])
- end = atoi (&myargv[2][1]);
- else
- end = atoi (myargv[3]);
- if (start < 0 || start > m->nmsgs || end < 0 || end > m->nmsgs)
- tprintf (Badrange, start, end);
- else
- for (i = start; i <= end; i++) {
- msg = i;
- dodeleting (m, msg);
- } /* endfor */
- } else
- for (i = 1; i < argc; ++i) {
- tmpbuf = strchr (myargv[i], '-'); /* N5KNX: allow from-to msg specification */
- msg = atoi (myargv[i]);
- if (tmpbuf == NULLCHAR)
- maxmsg = msg;
- else
- maxmsg = atoi (++tmpbuf);
- if (maxmsg < msg) {
- tprintf (Badmsg, myargv[i]);
- continue;
- }
- for (; msg <= maxmsg; msg++) {
- if (msg < 0 || msg > m->nmsgs) {
- tprintf (Badmsg, msg);
- continue;
- }
- dodeleting (m, msg);
- }
- }
- /* If this was 'KM'
- * free the memory allocated for myargv[] - WG7J
- */
- if (m->stype == 'M') {
- for (i = 1; i < argc; i++)
- free (myargv[i]);
- }
- return 0;
- }
-
-
-
- struct clparms {
- int nostatus, nodelete;
- long *hostsize;
- long _hostsize;
- char name[20]; /* Name of remote station */
- char area[64]; /* name of current mail area */
- FILE *mfile; /* mail data file pointer */
- struct let *mbox;
- int nmsgs; /* number of messages in this mail box */
- int isbbs;
- };
-
-
- static void
- close_notes (int a OPTIONAL, void *b, void *c OPTIONAL)
- {
- struct clparms *cl;
- struct let *cmsg;
- char *line;
- char tstring[LINELEN], buf[256];
- char buf2[256];
- long size, diff;
- FILE *nfile;
- int i, nextisBID, numwritten = 0;
- int foundstatus, firstIDline;
- #if 0
- char *cp;
- long msgid;
- #endif
-
- cl = (struct clparms *) b;
- line = tstring;
- sprintf (buf, "%s/control/%s.ctl", Mailspool, cl->area);
- (void) remove (buf);
-
- (void) fclose (cl->mfile);
- sprintf (buf, "%s/%s.txt", Mailspool, cl->area);
- sprintf (buf2, "%s/%s.bak", Mailspool, cl->area);
- (void) remove (buf2); /* delete it here, just in case! */
- (void) rename (buf, buf2);
- if ((cl->mfile = subdir_fopen (buf2, READ_TEXT)) == NULLFILE) {
- rmlock (Mailspool, cl->area);
- free (cl);
- return;
- }
- if ((nfile = subdir_fopen (buf, WRITE_TEXT)) == NULLFILE) {
- (void) fclose (cl->mfile);
- rmlock (Mailspool, cl->area);
- free (cl);
- return;
- }
- /* copy tmp file back to notes file */
- for (cmsg = &cl->mbox[1], i = 1; i <= cl->nmsgs; i++, cmsg++) {
- fseek (cl->mfile, cmsg->start, 0);
- kwait (NULL);
- cmsg->start = ftell (nfile);
- size = cmsg->size;
- diff = 0;
- foundstatus = 0;
- /* It is not possible to delete messages if nodelete is set */
- if ((cmsg->status & BM_DELETE) && !cl->nodelete)
- continue;
- nextisBID = 0;
- firstIDline = 0;
- /* copy the header */
- while (size > 0 && fgets (line, LINELEN, cl->mfile) != NULLCHAR) {
- kwait (NULL); /* can cause problems if exiting NOS */
- #if 0
- if (!firstIDline && nextisBID && (cp = strstr (line, "AA")) != NULLCHAR) {
- /*what follows is the message-number*/
- msgid = atol (cp + 2);
- #else
- if (!firstIDline && nextisBID && strstr (line, "AA") != NULLCHAR) {
- #endif
- nextisBID = 0;
- firstIDline = 1;
- }
- if (!strncmp (line, Hdrs[RECEIVED], strlen (Hdrs[RECEIVED])))
- nextisBID = 1;
- if (!strncmp (line, Hdrs[STATUS], strlen (Hdrs[STATUS])))
- foundstatus = 1;
- size -= (long) strlen (line);
- if (*line == '\n') {
- #ifdef notagain
- if (cmsg->status & BM_FORWARDED) {
- fprintf (nfile, "%s%s\n", Hdrs[XFORWARD],
- cl->name);
- diff += (strlen (Hdrs[XFORWARD]) + strlen (cl->name) + 1);
- }
- #endif
- if (!foundstatus && (cmsg->status & BM_READ) != 0 && !cl->nostatus) {
- fprintf (nfile, "%sR\n", Hdrs[STATUS]);
- diff += (long) (strlen (Hdrs[STATUS]) + 2);
- }
- fprintf (nfile, "\n");
- break;
- }
- fputs (line, nfile);
- kwait (NULL); /* can cause problems if exiting NOS */
- }
- kwait (NULL);
- while (size > 0 && fgets (line, LINELEN, cl->mfile) != NULLCHAR) {
- kwait (NULL); /* can cause problems if exiting NOS */
- if (!cl->nostatus && !strncmp (line, Hdrs[RRECEIPT], strlen (Hdrs[RRECEIPT]))
- && !strcmp (cl->name, cl->area) && (cmsg->status & BM_RRECEIPT)) {
- fputs ("Return-Receipt-Sent\n", nfile);
- diff -= (long) strlen (line);
- diff += 20;
- } else
- fputs (line, nfile);
- size -= (long) strlen (line);
- kwait (NULL); /* dont want no damaged files */
- if (ferror (nfile)) {
- (void) fclose (nfile);
- (void) fclose (cl->mfile);
- rmlock (Mailspool, cl->area);
- free (cl);
- return;
- }
- }
- cmsg->status &= BM_READ;
- cmsg->size += diff;
- updateCtl (cl->area, cmsg);
- (void) fflush (nfile);
- numwritten++;
- }
- if (!cl->isbbs && !stricmp (cl->name, cl->area))
- *cl->hostsize = ftell (nfile); /* Update the size of our hosts' mailbox */
- /* potientially dangerous! */
- /* remove a zero length file */
- if (!numwritten) {
- (void) fclose (nfile);
- (void) unlink (buf);
- } else
- (void) fclose (nfile);
- (void) fclose (cl->mfile);
- (void) remove (buf2); /* leave it around, for now! NOT! */
- rmlock (Mailspool, cl->area);
- free (cl->mbox);
- free (cl);
- kwait (NULL);
- return;
- }
-
-
-
- /* close the temp file while coping mail back to the mailbox */
- int
- closenotes (struct mbx *m, int exiting)
- {
- int nostatus, nodelete = 0;
- struct clparms *cl;
-
- if (m->mfile == NULLFILE || !*m->area)
- return 0;
- nostatus = issysarea (m->area);
-
- /* Allow any user to delete from area names starting with 'nts' */
- if (!strnicmp (m->area, "nts", 3))
- nostatus = 0;
- if (!(m->change & CHG_NORMAL) || nostatus) { /* no changes were made (or bulletin) */
- mfclose (m);
- m->mboxsize = 0;
- return 0;
- }
- /* If this area is not our own private message area, then we will not add a
- * Status line to indicate that the message has been read.
- */
- if (strcmp (m->area, m->name)) {
- nostatus = 1;
- /* Don't delete messages from public message areas unless you are
- * a SYSOP.
- */
- nodelete = !(m->privs & SYSOP_CMD);
- }
- /* Allow any user to delete from area names starting with 'nts' */
- if (!strnicmp (m->area, "nts", 3))
- nodelete = 0;
- /* If not a SYSOP, not an "nts" area, not our area, AND deletions, must be BBS forward */
- if (m->change & CHG_DELETE) {
- nodelete = 0;
- log (-1, "PBBS forwarding rewrite of personal area '%s' by %s ", m->area, m->name);
- }
- if (nostatus && nodelete) {
- mfclose (m);
- m->mboxsize = 0;
- return 0;
- }
- scanmail (m);
- if (lockit (m))
- return -1;
- cl = (struct clparms *) mallocw (sizeof (struct clparms));
-
- cl->nodelete = nodelete;
- cl->nostatus = nostatus;
- if (!exiting)
- cl->hostsize = &m->mysize;
- else {
- cl->_hostsize = m->mysize;
- cl->hostsize = &cl->_hostsize;
- }
- cl->isbbs = (m->sid & MBX_SID);
- strncpy (cl->name, m->name, 20);
- strncpy (cl->area, m->area, 64);
- cl->mfile = m->mfile;
- cl->nmsgs = m->nmsgs;
- cl->mbox = m->mbox;
- (void) newproc ("Closing notefile", 2560, close_notes, 0, cl, 0, 0);
- kwait (NULL);
- m->mfile = NULLFILE;
- m->mbox = (struct let *) 0;
- mfclose (m);
- m->mboxsize = 0;
- return 0;
- }
-
- #endif /* MAILCMDS */
-
-
-
- /* Returns 1 if name is in the given area file, 0 otherwise */
- static int
- is_area (const char *name, const char *listfile)
- {
- char buf[LINELEN], *cp;
- FILE *fp;
-
- if ((fp = fopen (listfile, READ_TEXT)) == NULLFILE)
- return 0;
- while (fgets (buf, sizeof (buf), fp) != NULLCHAR) {
- /* The first word on each line is all that matters */
- if (isalnum (buf[0])) { /* skip comments */
- if ((cp = strpbrk (buf, " \t\n")) != NULLCHAR)
- *cp = '\0';
- (void) nntp_name_expansion (buf);
- if (stricmp (name, buf) == 0) { /* found it */
- (void) fclose (fp);
- return 1;
- }
- }
- }
- (void) fclose (fp);
- return 0;
- }
-
-
-
- /* Returns 1 if name is a public message Area, 0 otherwise */
- int
- isarea (const char *name)
- {
- return (is_area2 (name));
- }
-
-
-
- /* Returns 1 if name is a public message Area, 0 otherwise */
- int
- issysarea (const char *name)
- {
- return (is_area (name, AreaSlist));
- }
-
-
-
- #ifdef MAILCMDS
- int
- lockit (struct mbx *m)
- {
- int c, cnt = 0;
-
- while (mlock (Mailspool, m->area)) {
- (void) kpause (1000L); /* Wait one second */
- if (++cnt == 10) {
- char buf[80];
-
- sprintf (buf, "Mail file '%s' is busy, Abort or *Retry ? ", m->area);
- cnt = 0;
- c = tkeywait (buf, 1, m->linemode);
- if (c == 'A' || c == 'a' || c == EOF) {
- mfclose (m);
- return 1;
- }
- }
- }
- return 0;
- }
-
-
-
- /* read the next message or the current one if new */
- int
- doreadnext (int argc OPTIONAL, char *argv[]OPTIONAL, void *p)
- {
- struct mbx *m;
- char buf[14], *newargv[2], buf2[6];
-
- m = (struct mbx *) p;
- if (m->mfile == NULLFILE)
- return 0;
- if ((m->mbox[m->current].status & BM_READ) != 0) {
- if (m->current == 1 && m->anyread == 0)
- ;
- else if (m->current < m->nmsgs)
- m->current++;
- else {
- tputs ("Last message\n");
- return 0;
- }
- }
- sprintf (buf, "%d", m->current);
- strcpy (buf2, "read");
- newargv[0] = buf2;
- newargv[1] = buf;
- return doreadmsg (2, newargv, p);
- }
-
- #endif
-
-
-
- #ifdef SAMCALLB
- void
- leadingCaps (char *str, int others)
- {
- char *cp;
-
- cp = str;
- (void) strlwr (cp);
- if (!others) {
- if ((cp = strchr (cp, ' ')) != 0)
- (void) strupr (cp);
- return;
- }
- do {
- cp = strchr (cp, ' ');
- if (cp != NULL) {
- cp = skipwhite (cp);
- *cp = (char) toupper (*cp);
- }
- } while (cp);
- }
- #endif
-
-
- char *
- mblookname (struct mbx *m, char *str)
- {
- if ((m != NULLMBX) && (m->realname) && (*m->realname == '(') && (m->realname[1] != ')'))
- return (strdup (m->realname));
-
- if (strchr (str, '('))
- return (0); /* already has a name */
- #ifdef SAMCALLB
- return (cb_lookname (str));
- #else
- return (0);
- #endif
- }
-
-
-
- #ifdef MAILCMDS
-
- extern int MbRead;
-
- /* display message on the crt given msg number */
- /* Modified to allow the 'RM' command, 920307 - WG7J */
- int
- doreadmsg (int argc, char *argv[], void *p)
- {
- struct mbx *m;
- register int c, col, lin;
- unsigned char buf[MAXBUF + 2], *cp, *cp2;
- char *subj = 0, *theto = 0;
- int msg, cnt, i, usemore = 0, verbose, mbxheader, pathcol = 5;
- int header, lastheader;
- long size;
- char *myargv[NARG];
- int myargc;
- int maxmsg;
- struct let *cmsg;
- char *tmpbuf;
- char *returnreceipt;
- #ifdef USERLOG
- long msgid;
- #endif
-
- m = (struct mbx *) p;
-
- /*Check for read-permissions - WG7J */
- if (m->privs & NO_READCMD) {
- tputs (Noperm);
- return 0;
- }
- #ifdef MBFWD
- if (m->stype == 'O')
- return (dombroute (argc, argv, p));
- #endif
- if ((m->mfile == NULLFILE) || (m->nmsgs == 0)) {
- if (!(m->privs & ALL_AREAS))
- tputs (Nomail);
- return 0;
- }
- if ((lin = m->morerows) != 0)
- usemore = 1; /* Display More prompt */
-
- /*If this is the RM or VM command, setup myargv[]
- *to contain up to NARG message numbers - WG7J
- */
- if (m->stype == 'M') {
- myargc = 1;
- if (!m->newmsgs) {
- tputs (Nomail);
- return 0;
- }
- /* scan all messsages to find unread ones */
- maxmsg = min (m->nmsgs, m->current + NARG - 2);
- for (i = m->current; i <= maxmsg; i++) {
- cmsg = &m->mbox[i];
- if (!(cmsg->status & BM_READ)) { /*found an unread msg!*/
- tmpbuf = mallocw (18); /*allocate space for the new argument*/
- myargv[myargc++] = itoa (i, tmpbuf, 10);
- }
- }
- argc = myargc;
- } else {
- /*simply point to the old arguments*/
- for (i = 1; i < argc; i++)
- myargv[i] = argv[i];
- }
- if (argc == 1) {
- tputs ("Usage: Read/Verbose #\n");
- return 0;
- }
- m->state = MBX_READ;
- for (i = 1; i < argc; ++i) {
- msg = atoi (myargv[i]); /*lint !e644 */
- if (msg < 1 || msg > m->nmsgs) {
- if (!(m->privs & ALL_AREAS))
- tprintf (Badmsg, msg);
- goto iamdone;
- }
- MbRead++;
- fseek (m->mfile, m->mbox[msg].start, 0);
- #ifdef USERLOG
- /* Check the ID number of this message and
- * adjust new lastread count, if needed - WG7J
- */
- (void) fgets ((char *) buf, MAXBUF + 2, m->mfile); /* the 'From ' line */
- (void) fgets ((char *) buf, MAXBUF + 2, m->mfile); /* the 'Received: ' line */
- (void) fgets ((char *) buf, MAXBUF + 2, m->mfile); /* the ' ID' line */
- /* find id number */
- if ((cp = (unsigned char *) strstr ((char *) buf, "AA")) != (unsigned char *) 0) {
- /*what follows is the message-number*/
- msgid = atol ((char *) cp + 2);
- if ((msgid > m->lastread) && (msgid > m->newlastread))
- m->newlastread = msgid;
- }
- fseek (m->mfile, m->mbox[msg].start, 0);
- #endif
- #ifdef nope /* was USERLOG */
- if ((m->mbox[msg].bid > m->lastread) && (m->mbox[msg].bid > m->newlastread))
- m->newlastread = m->mbox[msg].bid;
- #endif
-
- m->anyread = 1;
- returnreceipt = 0;
- size = m->mbox[msg].size;
- m->current = msg;
- header = NOHEADER;
- mbxheader = 0;
- if ((*argv[0] == 'v') || (m->stype == 'H'))
- verbose = 1; /* display all header lines */
- else
- verbose = 0;
-
- m->inmessage = 1;
- if (m->stype != 'M')
- bbscolorcls (m);
- bbscolorchange (m, "07");
- if (m->sid & MBX_HTTP)
- tprintf ("<PRE>\n");
- tprintf ("Message #%d %s\n", msg,
- m->mbox[msg].status & BM_ONHOLD ? "[On Hold - Awaiting Review of SYSOP]" :
- m->mbox[msg].status & BM_DELETE ? "[Deleted]" : "");
-
- if ((m->mbox[msg].status & (BM_ONHOLD | BM_DELETE)) && !(m->privs & SYSOP_CMD))
- continue;
-
- /* When you have sysop privs,
- * only mark your own private area as read and changed.
- * other areas, only mark as read, NOT changed !
- * for regular users, simply mark all as read and changed.
- * That way sysops can read other's mail without
- * marking stuff read that really wasn't read by
- * the right person !
- * for regular users, simply mark as read.
- * 910312 - WG7J
- */
- if (!(m->mbox[msg].status & BM_READ)) {
- m->mbox[msg].status |= BM_READ;
- /* regular users */
- if (!issysarea (m->area) && (!(m->privs & SYSOP_CMD) || ((m->privs & SYSOP_CMD) && !strcmp (m->name, m->area)))) /*sysops*/
- m->change |= CHG_READ;
- m->newmsgs--;
- }
- --lin;
- col = 0;
- while (!feof (m->mfile) && size > 0) {
- for (col = 0; col < MAXBUF;) {
- c = getc (m->mfile);
- size--;
- if (feof (m->mfile) || size == 0) /* end this line */
- break;
- if (c == '\t') {
- cnt = col + 8 - (col & 7);
- if (cnt >= MAXBUF) /* end this line */
- break;
- while (col < cnt)
- buf[col++] = ' ';
- } else {
- if (c == '\n')
- break;
- buf[col++] = uchar (c);
- }
- }
- if (col < MAXBUF)
- buf[col++] = '\n';
- buf[col] = '\0';
- if (mbxheader > 0) {
- /* Digest R: lines and display as a Path: line */
- if (strnicmp ((char *) buf, "R:", 2) != 0 || (cp = (unsigned char *) strchr ((char *) buf, '@')) == (unsigned char *) 0) {
- tputc ('\n');
- bbscolorchange (m, "0B");
- mbxheader = -1; /* don't get here again */
- verbose = 1;
- } else {
- if (*(++cp) == ':')
- ++cp;
- for (cp2 = cp; isalnum (*cp2); ++cp2)
- ;
- *cp2 = '\0';
- if (mbxheader++ == 1) {
- bbscolorchange (m, "07");
- tputs (Hdrs[PATH]);
- pathcol = 5;
- --lin;
- } else {
- tputc ('!');
- if (++pathcol + (int) strlen ((char *) cp) > MAXCOL - 3) {
- tputs ("\n ");
- pathcol = 5;
- --lin;
- }
- }
- tputs ((char *) cp);
- pathcol += (int) strlen ((char *) cp);
- ++lin; /* to allow for not printing it later */
- }
- }
- if (col == 1 && !mbxheader) {
- bbscolorchange (m, "0B");
- /* last header line reached */
- if (!verbose)
- mbxheader = 1;
- }
- if (verbose)
- /* tputs (buf); */
- (void) colorprintf (NULLCHAR, m->usecolor, buf);
- if (!strncmp (Hdrs[RRECEIPT], (char *) buf, strlen (Hdrs[RRECEIPT])))
- returnreceipt = strdup ((char *) &buf[strlen (Hdrs[RRECEIPT])]);
- if (!verbose && !mbxheader) {
- lastheader = header;
- if (!isspace (*buf))
- header = htype ((char *) buf);
- else
- header = lastheader;
- switch (header) {
- case SUBJECT:
- subj = strdup ((char *) &buf[strlen (Hdrs[SUBJECT]) - 4]);
- tputs ((char *) buf);
- break;
- case MSGID:
- #ifdef MBFWD
- /* give a "traditional BBS" version to the user */
- {
- char bid[LINELEN];
-
- (void) makeBBSbid (bid, sizeof (bid), (char *) buf);
- (void) strupr (bid);
- tprintf ("%s%s\n", Hdrs[MSGID], bid);
- }
- break;
- #endif
- case TO:
- theto = strdup ((char *) &buf[strlen (Hdrs[TO])]);
- /* fall through */
- case FROM:
- {
- char *nm;
-
- rip ((char *) buf);
- tputs ((char *) buf);
- nm = strchr ((char *) buf, ' ');
- if (nm && (nm = mblookname (NULLMBX, ++nm)) != 0) {
- tputs (nm);
- free (nm);
- }
- tputc ('\n');
- }
- break;
- case CC:
- case DATE:
- case REPLYTO:
- case APPARTO:
- case ERRORSTO:
- case XMAILGROUP:
- case ORGANIZATION:
- tputs ((char *) buf);
- break;
- case XBBSHOLD:
- if (m->privs & SYSOP_CMD)
- tputs ((char *) buf);
- break;
- default:
- ++lin;
- }
- }
- col = 0;
- if (usemore && --lin <= 0) {
- if (m->type == TELNET || m->type == TIP)
- c = tkeywait ("--More--", 0, m->linemode);
- else /* For AX.25 and NET/ROM connects - WG7J */
- c = mykeywait (anymore, m);
- #ifdef MBXTDISC
- start_timer (&m->tdisc);
- #endif
- lin = m->morerows;
- if (c == -1 || c == 'q' || c == 'Q')
- break;
- #ifdef TNOS_68K
- if (c == '\l' || c == '\r')
- #else
- if (c == '\n' || c == '\r')
- #endif
- lin = 1;
- }
- } /* while !eof */
- #ifdef TUTOR
- {
- char savbuf[MBXLINE + 1];
-
- memcpy (savbuf, m->line, MBXLINE + 1);
- sprintf (m->line, "msgend %d", msg);
- mbscripthook (m, "msgend.sys");
- memcpy (m->line, savbuf, MBXLINE + 1);
- }
- #endif
- if (returnreceipt && !MBnoReturnReceipt && !(m->mbox[msg].status & BM_RRECEIPT)) {
- struct mbx *mm;
-
- m->mbox[msg].status |= BM_RRECEIPT;
- rip (returnreceipt); /* strip off <CR> */
- tprintf ("[Sending return receipt to '%s']\n", returnreceipt);
- mm = (struct mbx *) mallocw (sizeof (struct mbx));
-
- mm->tomsgid = mm->date = mm->origbbs = mm->tofrom = NULLCHAR;
- mm->origto = returnreceipt;
- if (!subj)
- subj = strdup (" No subject");
- mm->subject = subj;
- mm->realname = strdup ("()");
- rip (subj); /* strip off <CR> */
- subj[0] = subj[1] = 'R';
- subj[2] = ':';
- subj[3] = ' ';
- mm->stype = 'P';
- strncpy (mm->name, m->name, 20);
- if ((mm->tfile = tmpfile ()) != NULLFILE) {
- struct list *cclist = NULLLIST;
- char fullfrom[MBXLINE];
-
- (void) addlist (&cclist, returnreceipt, 0, returnreceipt);
- sprintf (fullfrom, "%s@%s", m->name, Hostname);
- (void) mbx_data (mm, NULLLIST, NULLCHAR, 0);
- if (!theto)
- theto = strdup ("unknown addressee");
- rip (theto); /* strip off the <CR> */
- fprintf (mm->tfile, "Message received - Originally addressed to: '%s'\n", theto);
- fseek (mm->tfile, 0L, 0); /* rewind file */
- (void) queuejob (mm->tfile, Hostname, cclist, fullfrom);
- (void) fclose (mm->tfile);
- del_list (cclist);
- smtptick (NULL); /* wake up SMTP to send mail */
- }
- free (mm->realname);
- free (mm);
- free (returnreceipt);
- }
- free (subj);
- free (theto);
- m->inmessage = 0;
- #ifdef STATS_AREA
- STATS_addarea (1, 1, m->area);
- #endif
- } /* for argc */
- iamdone:
- /* If this was 'RM' or 'VM',
- * free the memory allocated for myargv[] - WG7J
- */
- if (m->stype == 'M') {
- for (i = 1; i < argc; i++)
- free (myargv[i]);
- }
- if (m->sid & MBX_HTTP)
- tprintf ("</PRE>\n");
- return 0;
- }
-
-
-
- /* Set up m->to when replying to a message. The subject is returned in
- * m->line.
- */
- int
- mbx_reply (
- int argc,
- char *argv[],
- struct mbx *m,
- struct list **cclist, /* Pointer to buffer for pointers to cc recipients */
- char **rhdr /* Pointer to buffer for extra reply headers */
- ) {
- char subject[MBXLINE], *msgid = NULLCHAR, *date = NULLCHAR;
- char *cp;
- int msg, lastheader, header = NOHEADER, k;
- long size;
-
- /* Free anything that might be allocated
- * since the last call to mbx_to() or mbx_reply()
- */
- free (m->to);
- m->to = NULLCHAR;
- free (m->tofrom);
- m->tofrom = NULLCHAR;
- free (m->tomsgid);
- m->tomsgid = NULLCHAR;
- free (m->origto);
- m->origto = NULLCHAR;
- subject[0] = '\0';
-
- if (argc == 1)
- msg = m->current;
- else
- msg = atoi (argv[1]);
- if (m->mfile == NULLFILE) {
- if (m->sid & MBX_SID)
- tputs ("NO - ");
- tputs (Nomail);
- return 0;
- }
- if (msg < 1 || msg > m->nmsgs) {
- if (m->sid & MBX_SID)
- tputs ("NO - ");
- tprintf (Badmsg, msg);
- return -1;
- }
- fseek (m->mfile, m->mbox[msg].start, 0);
- size = m->mbox[msg].size;
- m->current = msg;
- while (size > 0 && fgets (m->line, MBXLINE - 1, m->mfile) != NULLCHAR) {
- size -= (long) strlen (m->line);
- if (m->line[0] == '\n') /* end of header */
- break;
- rip (m->line);
- lastheader = header;
- if (!isspace (m->line[0])) {
- header = htype (m->line);
- lastheader = NOHEADER;
- }
- switch (header) {
- case SUBJECT:
- trimright (m->line);
- if (strlen (m->line) > 11 && !strnicmp (&m->line[9], "Re:", 3))
- strncpy (subject, &m->line[9], MBXLINE);
- else {
- strcpy (subject, "Re: ");
- strncpy (&subject[4], &m->line[9], MBXLINE - 4);
- }
- break;
- case FROM:
- trimright (m->line);
- if (m->to == NULLCHAR && (cp = getaddress (m->line, 0)) !=
- NULLCHAR)
- m->to = strdup (cp);
- break;
- case REPLYTO:
- if ((cp = getaddress (m->line, 0)) != NULLCHAR) {
- free (m->to);
- m->to = strdup (cp);
- }
- break;
- case MSGID:
- trimright (m->line);
- free (msgid);
- msgid = strdup (&m->line[12]);
- break;
- case DATE:
- free (date);
- date = strdup (&m->line[6]);
- break;
- #ifdef notdef
- /* don't want a reply back to myself - WG7J */
- case TO:
- case APPARTO:
- #endif
- case CC:
- /* Get addresses on To, Cc and Apparently-To lines */
- cp = m->line;
- k = (int) (strlen (cp) + 1);
- m->line[min(k, MBXLINE)] = '\0'; /* add extra null at end */
- for (;;) {
- if ((cp = getaddress (cp, lastheader == header || cp != m->line)) == NULLCHAR)
- break;
- (void) addlist (cclist, cp, 0, cp);
- /* skip to next address, if any */
- cp += strlen (cp) + 1;
- }
- break;
- default:
- break;
- }
- }
- if (msgid != NULLCHAR || date != NULLCHAR) {
- *rhdr = mallocw (LINELEN);
- sprintf (*rhdr, "In-Reply-To: your message ");
- if (date != NULLCHAR) {
- sprintf (m->line, "of %s.\n", date);
- strcat (*rhdr, m->line);
- if (msgid != NULLCHAR)
- strcat (*rhdr, " ");
- }
- if (msgid != NULLCHAR) {
- sprintf (m->line, "%s\n", msgid);
- strcat (*rhdr, m->line);
- }
- free (msgid);
- free (date);
- }
- strncpy (m->line, subject, MBXLINE);
- return 0;
- }
-
-
-
- #ifdef USERLOG
-
- /*get the last message listed/read
- *from the areaname.USR file
- *keeps track for each user.
- *February '92, WG7J
- */
- void
- getlastread (struct mbx *m)
- {
- FILE *Alog;
- char buf[256];
- char *cp;
- int found = 0;
-
- m->lastread = m->newlastread = 0L;
-
- sprintf (buf, "%s/users/%s.usr", Mailspool, m->area);
- if ((Alog = subdir_fopen (buf, "r+")) == NULLFILE) {
- /* USR file doesn't exist, create it */
- if ((Alog = subdir_fopen (buf, "w")) == NULLFILE)
- return;
- /* Add this user as first one */
- sprintf (buf, "%s 0\n", m->name);
- fputs (buf, Alog);
- (void) fclose (Alog);
- return;
- }
- /*Find user in the usr file for this area*/
- for (;;) {
- if (fgets (buf, sizeof (buf), Alog) == NULLCHAR)
- break;
- if ((cp = strchr (buf, ' ')) != NULLCHAR) {
- *cp = '\0';
- if (!stricmp (m->name, buf)) {
- /*found user*/
- cp++;
- while (*cp == ' ') /*skip blanks*/
- cp++;
- m->lastread = atol (cp);
- found = 1;
- break;
- }
- }
- }
- if (!found) {
- /*Add user*/
- sprintf (buf, "%s 0\n", m->name);
- fputs (buf, Alog);
- }
- (void) fclose (Alog);
- return;
- }
-
-
-
- /* Write the new last read id number to the USR file - WG7J
- * only update if this is not a bbs,
- * current area is a public area and not 'help',
- * or anything that starts with 'sys',
- * and a new message was actually listed/read
- */
- void
- setlastread (struct mbx *m)
- {
- FILE *Alog, *tfile;
- char buf[256];
- char tmpname[80];
- char *cp;
- int doit = 0;
-
- if ((m->sid & MBX_SID) || (m->newlastread <= m->lastread))
- return;
-
- /* if(issysarea(m->area))
- if ((m->privs & MBX_SYSOP) || (stricmp(m->area, "help")))
- doit = 1; */
- if (isarea (m->area) && strcmp (m->area, "help"))
- doit = 1;
- if ((m->privs & SYSOP_CMD) && issysarea (m->area))
- doit = 1;
-
- if (doit) {
-
- #ifdef notdef
- tprintf ("SETLAST: %d\n", m->newlastread);
- #endif
-
-
- sprintf (buf, "%s/users/%s.usr", Mailspool, m->area);
-
- /* Rename the USR file to a tempfile */
- #ifdef UNIX
- strncpy (tmpname, buf, 75);
- strcat (tmpname, ".bak");
- #else
- (void) tmpnam (tmpname);
- #endif
- if (rename (buf, tmpname))
- /* Can't rename ??? */
- return;
-
- if ((Alog = subdir_fopen (buf, "w")) == NULLFILE) {
- /* can't creat new USR file ???*/
- (void) rename (tmpname, buf); /* try to undo the damage */
- return;
- }
- if ((tfile = subdir_fopen (tmpname, "r")) == NULLFILE)
- /* can't open renamed file ??? */
- return;
-
- /*Write all users back, but update this one!*/
- while (fgets (buf, sizeof (buf), tfile) != NULLCHAR) {
- if ((cp = strchr (buf, ' ')) != NULLCHAR)
- *cp = '\0';
- if (!stricmp (m->name, buf)) {
- /*found this user*/
- sprintf (buf, "%s %lu\n", m->name, m->newlastread);
- } else if (cp)
- *cp = ' '; /* restore the space !*/
- fputs (buf, Alog);
- }
- (void) fclose (tfile);
- unlink (tmpname);
- (void) fclose (Alog);
- }
- return;
- }
-
- #endif /*USERLOG*/
-
-
-
- void
- scanmail (struct mbx *m)
- { /* Get any new mail */
- if (!isnewmail (m))
- return;
- if (lockit (m))
- return;
- (void) initnotes (m);
- rmlock (Mailspool, m->area);
- }
-
-
-
- /* Check the current mailbox to see if new mail has arrived.
- * Returns the difference in size.
- */
- static long
- isnewmail (struct mbx *m)
- {
- char buf[256];
-
- sprintf (buf, "%s/%s.txt", Mailspool, m->area);
- return fsize (buf) - m->mboxsize;
- }
-
-
-
- /* Check if the private mail area has changed */
- long
- isnewprivmail (struct mbx *m, const char *ext)
- {
- long cnt;
- char buf[256];
-
- sprintf (buf, "%s/%s.%s", Mailspool, m->name, ext);
- cnt = m->mysize;
- m->mysize = fsize (buf);
- return m->mysize - cnt; /* != 0 not more than once */
- }
-
-
-
- void
- notifynewmail (struct mbx *m)
- { /* not a BBS, but from within ANY area */
- if (!(m->sid & MBX_SID) && (isnewprivmail (m, "txt") > 0L)) {
- tprintf ("\007You have new mail in your personal area (%s). Please Kill when read!\n", m->name);
- usflush (Curproc->output);
- }
- }
-
- #endif
- #endif
-
-
-
- /* This function returns the length of a file. The proper thing would be
- * to use stat(), but it fails when using DesqView together with Turbo-C
- * code.
- */
- long
- fsize (char *name)
- {
- long cnt;
- FILE *fp;
-
- if ((fp = subdir_fopen (name, READ_TEXT)) == NULLFILE)
- return -1L;
- fseek (fp, 0L, 2);
- cnt = ftell (fp);
- /* cnt = filelength (fileno(fp)); */
- (void) fclose (fp);
- return cnt;
- }
-
-
-
- #ifdef MAILCMDS
- /* close the temporary mail file */
- static void
- mfclose (struct mbx *m)
- {
- if (m->mfile != NULLFILE)
- (void) fclose (m->mfile);
- m->mfile = NULLFILE;
- #ifdef SETVBUF
- free (m->stdoutbuf);
- m->stdoutbuf = NULLCHAR;
- #endif
- }
-
- #endif
-
-
-
- /* erase a previous prompt via backspaces */
- void
- backEmUp (int len)
- {
- int i;
-
- /* Get rid of the prompt */
- for (i = len; i != 0; i--)
- tputc ('\b');
- for (i = len; i != 0; i--)
- tputc (' ');
- for (i = len; i != 0; i--)
- tputc ('\b');
- tflush ();
- }
-
-
-
- /* Print prompt and read one character, telnet version */
- int
- tkeywait (
- const char *prompt, /* Optional prompt */
- int flush, /* Flush queued input? */
- int linemode /* Negotiate line mode? */
- ) {
- int c, cl, oldimode, oldomode;
-
- if (flush && socklen (Curproc->input, 0) != 0)
- (void) recv_mbuf (Curproc->input, NULL, 0, NULLCHAR, 0); /* flush */
- if (prompt == NULLCHAR)
- prompt = hitEnter;
- tprintf ("%s", prompt);
- /* hack - handle Unix telnet clients correctly */
- if (linemode)
- tprintf ("%c%c%c%c%c%c%c", IAC, SB, TN_LINEMODE, 1, 2, IAC, SE);
- tprintf ("%c%c%c", IAC, WILL, TN_ECHO);
- usflush (Curproc->output);
-
- /* discard the response */
-
- oldimode = sockmode (Curproc->input, SOCK_BINARY);
- oldomode = sockmode (Curproc->output, SOCK_BINARY);
-
- while ((c = rrecvchar (Curproc->input)) == IAC) {
- c = rrecvchar (Curproc->input);
- if (c == SB) {
- if ((c = rrecvchar (Curproc->input)) == EOF)
- break;
- cl = c;
- c = rrecvchar (Curproc->input);
- while ((c != EOF) && !(cl == IAC && c == SE)) {
- cl = c;
- c = rrecvchar (Curproc->input);
- }
- } else if (c > 250 && c < 255)
- (void) rrecvchar (Curproc->input);
- }
-
- (void) sockmode (Curproc->output, oldomode);
- (void) sockmode (Curproc->input, oldimode);
-
- backEmUp ((int) strlen (prompt));
- tprintf ("%c%c%c", IAC, WONT, TN_ECHO);
- if (linemode)
- tprintf ("%c%c%c%c%c%c%c", IAC, SB, TN_LINEMODE, 1, 1, IAC, SE);
- usflush (Curproc->output);
- return c;
- }
-
-
-
- /* Print -more- prompt and read reply,
- * AX.25 and NETROM version - WG7J
- * <CR> is taken as a 'Yes'
- */
- int
- mykeywait (char *prompt, struct mbx *m)
- {
- tputs (prompt);
- usflush (Curproc->output);
- if (recvline (m->user, (unsigned char *) m->line, MBXLINE) == -1) {
- return -1;
- }
- /* Only 'N' or 'n' really matters */
- if ((*m->line == 'N') || (*m->line == 'n'))
- return -1;
- return 0;
- }
-
-
-
- struct areas {
- struct areas *next;
- char *name;
- };
- static struct areas *Areas = NULL;
-
-
-
- static void
- readareas (const char *name)
- {
- FILE *fp;
- struct areas *ca = (struct areas *) 0, *na;
- char *cp, buf[FILE_PATH_SIZE];
-
- if ((fp = fopen (name, READ_TEXT)) == NULL)
- return;
-
- while (fgets (buf, sizeof (buf), fp) != NULL) {
- if (buf[0] == '#' || buf[0] == '-') /* comment line */
- continue;
- cp = buf;
- /* get first token on line */
- while (*cp) {
- if (*cp == '\n' || *cp == ' ' || *cp == '\t') {
- *cp = '\0';
- break;
- }
- cp++;
- }
- if (*buf) {
- na = (struct areas *) mallocw (sizeof (struct areas));
-
- na->name = strdup (buf);
- na->next = NULL;
- if (Areas == NULL)
- Areas = na;
- else if (ca)
- ca->next = na;
- ca = na;
- }
- }
- (void) fclose (fp);
- }
-
-
-
- static int
- is_area2 (const char *name)
- {
- #ifdef MAILCMDS
- struct areas *a;
-
- if (!Areas)
- readareas (Arealist);
-
- a = Areas;
-
- while (a) {
- if (stricmp (a->name, name) == 0)
- return 1;
- a = a->next;
- }
- #endif
- return 0;
- }
-
-
-
- void
- freeareas (void)
- {
- struct areas *a;
-
- while (Areas) {
- a = Areas;
- Areas = Areas->next;
- if (a->name) /* should always be, but just in case */
- free (a->name);
- free (a);
- }
- }
-